package com.sansan.qiangji.task;

import com.sansan.qiangji.entity.device.Stacker;
import com.sansan.qiangji.entity.device.StackerParam;
import com.sansan.qiangji.entity.device.StackerParamDetail;
import com.sansan.qiangji.entity.warehouse.StackerTask;
import com.sansan.qiangji.service.impl.device.BeltServiceImpl;
import com.sansan.qiangji.service.impl.device.StackerParamDetailServiceImpl;
import com.sansan.qiangji.service.impl.device.StackerParamServiceImpl;
import com.sansan.qiangji.service.impl.device.StackerServiceImpl;
import com.sansan.qiangji.service.impl.warehouse.AsyncStackerServiceImpl;
import com.sansan.qiangji.service.impl.warehouse.StackerTaskServiceImpl;
import com.sansan.qiangji.service.impl.warehouse.TaskLogServiceImpl;
import com.sansan.qiangji.utils.plcUtils.TDPlcUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

@Component
@Async
@Slf4j
public class AsyncTask {
    private StackerServiceImpl stackerService;
    private StackerTaskServiceImpl stackerTaskService;
    private BeltServiceImpl beltService;
    private TaskLogServiceImpl taskLogService;
    private AsyncStackerServiceImpl asyncStackerService;
    private StackerParamServiceImpl stackerParamService;
    private StackerParamDetailServiceImpl stackerParamDetailService;

    @Resource
    public void setStackerService(StackerServiceImpl stackerService) {
        this.stackerService = stackerService;
    }

    @Resource
    public void setStackerTaskService(StackerTaskServiceImpl stackerTaskService) {
        this.stackerTaskService = stackerTaskService;
    }

    @Resource
    public void setBeltService(BeltServiceImpl beltService) {
        this.beltService = beltService;
    }

    @Resource
    public void setTaskLogService(TaskLogServiceImpl taskLogService) {
        this.taskLogService = taskLogService;
    }

    @Resource
    public void setAsyncStackerService(AsyncStackerServiceImpl asyncStackerService) {
        this.asyncStackerService = asyncStackerService;
    }

    @Resource
    public void setStackerParamService(StackerParamServiceImpl stackerParamService){
        this.stackerParamService = stackerParamService;
    }

    @Resource
    public void setStackerParamDetailService(StackerParamDetailServiceImpl stackerParamDetailService){
        this.stackerParamDetailService = stackerParamDetailService;
    }

    public Future<Boolean> checkStackerStatus(Stacker stacker) {
        TDPlcUtil tdPlcUtil = new TDPlcUtil(stacker.getStackerIP(), stacker.getStackerPort());
        Boolean connectResult = tdPlcUtil.isConnect();
        boolean isUpdate = false;
        if (connectResult) {
            log.info("【PLC通信】PLC在线，IP={}", stacker.getStackerIP());
        }
        if ((connectResult && !stacker.getStackerOnlineStatus()) || (!connectResult && stacker.getStackerOnlineStatus())) {
            stacker.setStackerOnlineStatus(!stacker.getStackerOnlineStatus());
            isUpdate = true;
        }
        if (!connectResult && stacker.getIsRefreshStackerParam()){
            stacker.setIsRefreshStackerParam(false);
            List<StackerParam> stackerParams = stackerParamService.findAll();
            List<StackerParamDetail> stackerParamDetails = stackerParamDetailService.findByStackerName(stacker.getStackerName());
            List<StackerParamDetail> stackerParamDetailsAdd = new ArrayList<>();
            List<StackerParamDetail> stackerParamDetailsDelete = new ArrayList<>();
            List<StackerParamDetail> stackerParamDetailsUpdate = new ArrayList<>();
            for (StackerParam stackerParam : stackerParams){
                if (stackerParamDetails.stream().anyMatch(e->e.getStackerParamName().equals(stackerParam.getStackerParamName()))){
                    // TODO: 2020/11/3 读取plc参数值并判断是否有更新

                }else {
                    StackerParamDetail stackerParamDetail = new StackerParamDetail();
                    BeanUtils.copyProperties(stackerParam, stackerParamDetail);
                    // TODO: 2020/11/3 读取plc并更新参数值
                    stackerParamDetailsAdd.add(stackerParamDetail);
                }
            }
            for (StackerParamDetail stackerParamDetail : stackerParamDetails){
                if (stackerParams.stream().noneMatch(e->e.getStackerParamName().equals(stackerParamDetail.getStackerParamName()))){
                    stackerParamDetailsDelete.add(stackerParamDetail);
                }
            }
            isUpdate = true;
        }
        if (isUpdate){
            stackerService.updateStacker(stacker);
        }
        tdPlcUtil.disConnect();
        return new AsyncResult<>(true);
    }

    public void pushProduct(String stackerTaskCode) {
        taskLogService.log(stackerTaskCode, "开始入库");
        StackerTask stackerTask = stackerTaskService.findByStackerTaskCode(stackerTaskCode);
        for (int i = 0; i < 1; i++) {
            if (stackerTask == null) {
                log.error("【入库任务】堆垛机任务不存在，stackerTaskCode={}", stackerTaskCode);
                break;
            }
            if (!stackerService.checkPushStatus(stackerTask)) {
                log.error("【入库任务】堆垛机非空闲状态，stackerTaskCode={}", stackerTaskCode);
                break;
            }
            if (!beltService.checkTakeStatus(stackerTask)) {
                log.error("【入库任务】传送带非空闲状态，stackerTaskCode={}", stackerTaskCode);
                break;
            }
            if (!beltService.takeProduct(stackerTask)) {
                log.error("【入库任务】传送带取货失败，stackerTaskCode={}", stackerTaskCode);
                break;
            }
            if (!stackerService.getProduct(stackerTask)) {
                log.error("【入库任务】堆垛机取货失败，stackerTaskCode={}", stackerTaskCode);
                break;
            }
            if (!stackerService.downProduct(stackerTask)) {
                log.error("【入库任务】堆垛机放货失败，stackerTaskCode={}", stackerTaskCode);
            }
        }
        asyncStackerService.deleteAsyncStackerTaskByStackerTaskCode(stackerTaskCode);
    }
}
